{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# C++的友元"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. 友元简介"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "① 生活中你的家有客厅(Public)，有你的卧室(Private)，客厅所有来的客人都可以进去，但是你的卧室是私有的，也就是说只有你能进去，但是呢，你也可以允许你的好闺蜜进去。\n",
    "\n",
    "② 在程序里，有些私有属性，也想让类外特殊的一些函数或者类进行访问，就需要用到友元的技术。\n",
    "\n",
    "③ 友元的目的就是让一个函数或者类访问另一个类中私有成员。\n",
    "\n",
    "④ 友元的关键字为 friend。\n",
    "\n",
    "⑤ 友元的三种实现：\n",
    "\n",
    "1. 全局函数做友元。\n",
    "2. 类做友元。\n",
    "3. 成员函数做友元。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "using namespace std;\n",
    "\n",
    "//建筑物类\n",
    "class Buiding\n",
    "{\n",
    "    //goodfriend全局函数是Buiding类好朋友，可以访问Buiding中私有成员\n",
    "    friend void goodfriend(Buiding* buiding);\n",
    "\n",
    "public:\n",
    "    Buiding()  //构造函数 赋初值\n",
    "    {\n",
    "        m_SittingRoom = \"客厅\";\n",
    "        m_BedRoom     = \"卧室\";\n",
    "    }\n",
    "\n",
    "public:\n",
    "    string m_SittingRoom; //客厅\n",
    "\n",
    "private:\n",
    "    string m_BedRoom;\n",
    "};\n",
    "\n",
    "//全局函数\n",
    "void goodfriend(Buiding *buiding)\n",
    "{\n",
    "    cout << \"好基友全局函数 正在访问：\" << buiding->m_SittingRoom << endl;\n",
    "    cout << \"好基友全局函数 正在访问：\" << buiding->m_BedRoom     << endl;\n",
    "\n",
    "}\n",
    "\n",
    "void test01()\n",
    "{\n",
    "    Buiding building;\n",
    "    goodfriend(&building);\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "    test01();\n",
    "\n",
    "    system(\"pause\");\n",
    "\n",
    "    return 0;\n",
    "\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行结果：  \n",
    " - 好基友全局函数 正在访问：客厅  \n",
    " - 好基友全局函数 正在访问：卧室  \n",
    " - 请按任意键继续. . ."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 友元类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "using namespace std;\n",
    "\n",
    "//类做友元\n",
    "class Building; //声明\n",
    "\n",
    "class GoodGay\n",
    "{\n",
    "public:\n",
    "    GoodGay();\n",
    "\n",
    "    void visit(); //参观函数 访问Building中的属性\n",
    "\n",
    "    Building* building;\n",
    "};\n",
    "\n",
    "class Building\n",
    "{\n",
    "    //GoodGay类是本类的好朋友，可以访问本类的私有成员\n",
    "    friend class GoodGay;\n",
    "\n",
    "public:\n",
    "    Building();\n",
    "\n",
    "public:\n",
    "    string m_SittingRoom; //客厅\n",
    "private:\n",
    "    string m_BedRoom; //卧室\n",
    "};\n",
    "\n",
    "//类外写成员函数，写类名的作用域\n",
    "\n",
    "//Building构造函数\n",
    "Building::Building()\n",
    "{\n",
    "    m_SittingRoom = \"客厅\";\n",
    "    m_BedRoom     = \"卧室\";\n",
    "}\n",
    "\n",
    "//GoodGay构造函数\n",
    "GoodGay::GoodGay()\n",
    "{\n",
    "    //创建建筑物对象\n",
    "    building = new Building;    //这里会调用Building的构造函数\n",
    "                                //new是创建什么样的数据类型，就返回什么样的数据类型的指针       \n",
    "}\n",
    "\n",
    "void GoodGay::visit()\n",
    "{\n",
    "    cout << \"好基友类正在访问：\" << building->m_SittingRoom << endl;\n",
    "\n",
    "    cout << \"好基友类正在访问：\" << building->m_BedRoom << endl;\n",
    "\n",
    "}\n",
    "\n",
    "void test01()\n",
    "{\n",
    "    GoodGay gg; //创建一个GoodGay的对象，会调用GoodGay构造函数，会创建一个building，然后调用building构造函数      \n",
    "    gg.visit();\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "    test01();\n",
    "\n",
    "    system(\"pause\");\n",
    "\n",
    "    return 0;\n",
    "\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行结果：  \n",
    " - 好基友类正在访问：客厅  \n",
    " - 好基友类正在访问：卧室  \n",
    " - 请按任意键继续. . ."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 成员函数做友元"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "using namespace std;\n",
    "\n",
    "class Building;\n",
    "class GoodGay\n",
    "{\n",
    "public:\n",
    "    GoodGay();\n",
    "\n",
    "    void visit();  //让visit函数可以访问Building中私有成员\n",
    "    void visit2(); //让visit2函数不可以访问Buildinng中私有成员\n",
    "\n",
    "    Building* building;\n",
    "};\n",
    "\n",
    "class Building\n",
    "{\n",
    "    //告诉编译器，GoodGay类下的visit成员函数作为本类的好朋友，可以访问私有成员           \n",
    "    friend void GoodGay::visit();\n",
    "\n",
    "public:\n",
    "    Building();\n",
    "\n",
    "public:\n",
    "    string m_SittingRoom; //客厅\n",
    "\n",
    "private:\n",
    "    string m_BedRoom; //卧室\n",
    "};\n",
    "\n",
    "// 类外实现构造函数\n",
    "Building::Building()\n",
    "{\n",
    "    m_SittingRoom = \"客厅\";\n",
    "    m_BedRoom     = \"卧室\";\n",
    "}\n",
    "\n",
    "GoodGay::GoodGay()\n",
    "{\n",
    "    building = new Building;\n",
    "}\n",
    "\n",
    "// 类外实现成员函数\n",
    "void GoodGay::visit()\n",
    "{\n",
    "    cout << \"visit 函数正在访问\" << building->m_SittingRoom << endl;\n",
    "    cout << \"visit 函数正在访问\" << building->m_BedRoom << endl;\n",
    "\n",
    "}\n",
    "\n",
    "void GoodGay::visit2()\n",
    "{\n",
    "    cout << \"visit2 函数正在访问\" << building->m_SittingRoom << endl;\n",
    "    //cout << \"visit 函数正在访问\" << building->m_BedRoom << endl;\n",
    "\n",
    "}\n",
    "\n",
    "void test01()\n",
    "{\n",
    "    GoodGay gg;\n",
    "    gg.visit();\n",
    "    gg.visit2();\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "    test01();\n",
    "    \n",
    "    system(\"pause\");\n",
    "\n",
    "    return 0;\n",
    "\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行结果： \n",
    " - visit 函数正在访问客厅  \n",
    " - visit 函数正在访问卧室  \n",
    " - visit2 函数正在访问客厅  \n",
    " - 请按任意键继续. . ."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.6.3",
   "language": "python",
   "name": "python3.6.3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "341.333px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
